#include "mainwindow.h"
#include "arblip.h"
#include "arbliplistitem.h"
#include <QDebug>
#include "arbliplistitem.h"
#include "math.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //add connection icon    
    connectionIcon = new WaveConnectionIcon();
    //FIXME:remove the sunken style
    connectionIcon->setFrameStyle(QFrame::NoFrame);
    connectionIcon->setFrameShape(QFrame::NoFrame);
    ui->statusBar->addPermanentWidget(connectionIcon);

    //create the wavelist model
    waveListModel = new WaveListModel(QList<WaveModel *>(), this);
    //set the model for the wave list view
    ui->listView->setModel( waveListModel );
    ui->listView->setContextMenuPolicy(Qt::ActionsContextMenu);
    ui->listView->addAction(ui->actionOpen_wave);

    //set default page
    ui->stackedWidget->setCurrentIndex(0);
    lastOpenedPanel = 0;

    //add blip display box
    arblipDisplay = new ARBliplist();
    ui->blipframe->setLayout(arblipDisplay);

    //TODO: reconsider this in the future.
    //default range in meters
    rangeLimit = 40000000; // earth...I think.


    // create MapControl
    mapControl = new MapControl(QSize(620,360));

    //map source selector
    QActionGroup* mapProviderGroup = new QActionGroup(this);
    osmAction = new QAction(tr("OpenStreetMap"), mapProviderGroup);
    yahooActionMap = new QAction(tr("Yahoo: Map"), mapProviderGroup);
    yahooActionSatellite = new QAction(tr("Yahoo: Satellite"), mapProviderGroup);
    //FIXME: we either need to find a fix for the google map provider or just remove it entirely...
    googleActionMap = new QAction(tr("Google: Map"), mapProviderGroup);
    osmAction->setCheckable(true);
    yahooActionMap->setCheckable(true);
    yahooActionSatellite->setCheckable(true);
    googleActionMap->setCheckable(true);
    osmAction->setChecked(true);

    createMapMenus();

    // create MapAdapter to get maps from
    mapAdapter = new OSMMapAdapter();

    // create a map layer with the mapadapter
    layer = new MapLayer("Custom Layer", mapAdapter);
    //TODO: this should be reconsidered in the future
    //this layer will hold the ardots
    ARLayer = new GeometryLayer("AR layer", mapAdapter);
    // add Layer to the MapControl
    mapControl->addLayer(layer);
    mapControl->addLayer(ARLayer);
    //load map
    mapControl->setZoom(15);
    mapControl->setView(QPointF(5.07757,51.5586));
    mapControl->setContentsMargins(0,0,0,0);

    // display the MapControl in the application
    QVBoxLayout* vBoxLayout = new QVBoxLayout;
    //zoomSlider = new QSlider(Qt::Horizontal);
    zoomSlider = ui->mapZoomSlider;

    zoomSlider->setValue(15);
    zoomSlider->setMaximum(mapAdapter->maxZoom());
    zoomSlider->setMinimum(mapAdapter->minZoom());

    vBoxLayout->addWidget(mapControl);

    ui->mapBox->setLayout(vBoxLayout);

    //when a blip itself is clicked on, display its data in the box
    connect(arblipDisplay->getListWidget(), SIGNAL(itemClicked(QListWidgetItem  *)),this, SLOT(displayBlipText(QListWidgetItem *)));
    //range slider changes number of blips displayed
   // connect(arblipDisplay->getRangeSlider(), SIGNAL(valueChanged(int)), this, SLOT(changeRangeLimit(int)));

    //range limit now changed by menus (is there a better way to do this???)
    connect(ui->setRangeLimit100km, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit100m, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit1km, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit200m, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit500m, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit50km, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit50m, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimit5km, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    connect(ui->setRangeLimitInfinite, SIGNAL(triggered()), this, SLOT(changeRangeLimit()));
    //----------------------


    //bind the map button
    connect(ui->showOnMap,SIGNAL(clicked()), this,  SLOT(goToMap()));
    //map zoom slider
    connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(zoomMap(int)));
    //sets the current location as the arblip location
    connect(ui->setLocation, SIGNAL(clicked()), this, SLOT(setARBlipLocation()));
    //react to map provider changes
    connect(mapProviderGroup, SIGNAL(triggered(QAction*)), this, SLOT(mapProviderSelected(QAction*)));
    //updates location label
    connect(mapControl, SIGNAL(viewChanged(QPointF,int)), this, SLOT(mapViewChanged(QPointF,int)));
    //add a new blip at the current location
    connect(ui->addBlipFromMap, SIGNAL(clicked()),this,SLOT(addNewBlipFromMap()));
    //set the map to a location given by a url
    connect(ui->gotolocation, SIGNAL(clicked()),this,SLOT(gotolocation()));

    //set client location
    connect(ui->setClientLocationZero,SIGNAL(triggered()),SLOT(setClientLocation()));
    connect(ui->setClientLocationTilburg,SIGNAL(triggered()),SLOT(setClientLocation()));
    connect(ui->setClientLocationNewYork,SIGNAL(triggered()),SLOT(setClientLocation()));
    connect(ui->setClientLocationLondon,SIGNAL(triggered()),SLOT(setClientLocation()));

    //bind the login button with the login action
    connect(ui->loginButton, SIGNAL(clicked()), this,  SLOT(login()));
    //Also bind the password box when the user hits enter
    connect(ui->passLine, SIGNAL(returnPressed()), this,  SLOT(login()));
    //bind the logout menu item with the logout action
    connect(ui->actionLogout, SIGNAL(triggered()), this,  SLOT(logout()));
    //and the select sever item
    connect(ui->actionPygowaveConnect,SIGNAL(triggered()),SLOT(selectServer()));
    connect(ui->localSeverConnect,SIGNAL(triggered()),SLOT(selectServer()));
    connect(ui->testSeverConnect,SIGNAL(triggered()),SLOT(selectServer()));
    connect(ui->actionOrient_lodge,SIGNAL(triggered()),SLOT(selectServer()));

    //bind the create button with the creation of a wave
    connect(ui->createWaveButton, SIGNAL(clicked()), this, SLOT(createWave()));
    //bind the state events from the controller to the crappy method here
    //connect(controller, SIGNAL(stateChanged(int)), this,  SLOT(stateHandler(int)));
    //open the selected wave
    connect(ui->actionOpen_wave, SIGNAL(triggered()), this, SLOT(openWave()));
    //bind the show list menu item to show a list of the users waves
    connect(ui->action_show_list, SIGNAL(triggered()), this,  SLOT(showWaveList()));
    //bind the show active menu item to show again the active wave
    connect(ui->action_show_active_wave, SIGNAL(triggered()), this,  SLOT(showActiveWave()));
    //add user to wave
    connect(ui->InviteNewUser, SIGNAL(clicked()),this, SLOT(inviteUserToWave()));

    connect(ui->editBlip,SIGNAL(clicked()),this,SLOT(editSelectedBlip_clicked()));
    connect(ui->deleteSelectedBlip,SIGNAL(clicked()),this,SLOT(deleteSelectedBlip_clicked()));

    //bind the cancel button (which will cancel any blip edit/submission)
    connect(ui->cancelSubmit, SIGNAL(clicked()),this,SLOT(cancelSubmit()));

    //set application state
    currentstate = MainWindow::NotLoggedIn;

}

MainWindow::~MainWindow()
{
    //FIXME: others stuffs to be done here?
    delete ui;
}

//Sever selection.
//later (hopefully) we'll support for severs outside of Pygowave
void MainWindow::selectServer()
{
    //get name from menu item clicked
    QAction *MenuItem = qobject_cast<QAction *>(sender());
    QString severname = MenuItem->text();

    //set severname
    ui->srvLine->setText(severname);

    ui->passLine->setText("");
    ui->srvLine->setText("");

    //if its a local pygowave sever, then we can fill in the details;
    if (severname == "192.168.56.3"){
    ui->srvLine->setText("192.168.56.3");
    ui->usrLine->setText("root");
    ui->passLine->setText("pygowave");
    }

    //if its the default fedOne sever, then we can fill in the details;
    if (severname == "orient-lodge"){
    ui->srvLine->setText("orient-lodge.com");
    ui->usrLine->setText("davide@orient-lodge.com");
    ui->passLine->setText("12345");
    }

    //if its a test mode we skip to the next page without connecting
    if (severname == "(test mode)"){
        ui->usrLine->setText("(test mode)");
        ui->passLine->setText("(test mode)");
        ui->srvLine->setText("(test mode)");
        }

    //flick page
    ui->stackedWidget->setCurrentIndex(0);
    lastOpenedPanel=0;
    //TODO: in future we can trigger the login if the user has saved their username/password for this sever
    //login();


}

//this is all what's required to enstablis a connection
void MainWindow::login(void)
{
    //if set to test mode,then flip the page without logging in
     if (  ui->srvLine->text() == "(test mode)"){
         ui->stackedWidget->setCurrentIndex(1);
         lastOpenedPanel=1;
         //set application state
         currentstate = MainWindow::ViewingWaves;
         return;
     }

     //check if we're dealing with a pygo wave server
    if( ui->pyGoRadio->isChecked() )
    {
        m_acm = new PyGoCommunicationManager::PyGoCommunicationManager(waveListModel, &arblips);
        m_acm->login(ui->srvLine->text(), ui->usrLine->text(), ui->passLine->text(), 61613); //port is default here
    }
    //or if we're dealing with a fed one server
    if( ui->fedOneRadio->isChecked() )
    {
        m_acm = new FedOneCommunicationManager::FedOneCommunicationManager(waveListModel, &arblips);
        m_acm->login(ui->srvLine->text(), ui->usrLine->text(), ui->passLine->text(), 9876); //port is default here
    }   

    //from now on, we don't care about what server implementation we're dealing with...
    ui->stackedWidget->setCurrentIndex(1);
    currentstate = MainWindow::ViewingWaves;
    connect(m_acm, SIGNAL(arblipsUpdated()), this, SLOT(acm_arblipsUpdated()));
}

void MainWindow::logout(void)
{
    //log out
    m_acm->logout();
    //stop the icon
    connectionIcon->stop();
    //redisplay the login page
    ui->stackedWidget->setCurrentIndex(0);
    lastOpenedPanel=0;

    //disable the menu shortcut to go back to the wavelist
    ui->action_show_list->setEnabled(false);
    //and the current wave
    ui->action_show_active_wave->setEnabled(false);

}

//shows the list of waves the user is subscribed to
void MainWindow::showWaveList(void)
{
    /*
    //if is there another wavelet opened, close it to avoid crashes
    if( wavelet != NULL )
    {
        controller->closeWavelet( wavelet->id() );
    }
    */
    //visualize the right page
    ui->stackedWidget->setCurrentIndex(1);
    lastOpenedPanel=1;
    //set application state
    currentstate = MainWindow::ViewingWaves;

}


//goes back to the active wave page
void MainWindow::showActiveWave(void)
{
    ui->stackedWidget->setCurrentIndex(2);
    lastOpenedPanel=2;
    //set application state
    currentstate = MainWindow::ViewingBlips;
}


//creates a new wave with a default empty blip
void MainWindow::createWave(void)
{
    //create a new empty wave
    m_acm->createWave( ui->waveTitleLine->text() );
}

/*
//this just displays info to the user...
//i don't know what the "int state" is for...
void MainWindow::stateHandler(int state)
{

    //pretty straight forward
    if( controller->state() == PyGoWave::Controller::ClientOnline )
    {
         connectionIcon->start();
         ui->statusBar->showMessage("Connection status: Online (state="+QString::number(state)+")");

         //set the page to the list of waves and the option to create new ones
         ui->stackedWidget->setCurrentIndex(1);
         lastOpenedPanel=1;
         //set application state
         currentstate = MainWindow::ViewingWaves;
         //enable the menu shortcut to go back to the wavelist
         ui->action_show_list->setEnabled(true);

        return;
    }

    if( controller->state() == PyGoWave::Controller::ClientConnected )
    {
        connectionIcon->start();
        ui->statusBar->showMessage("Connection status: Connected (state="+QString::number(state)+")");

        return;
    }

    if( controller->state() == PyGoWave::Controller::ClientDisconnected )
    {
        connectionIcon->stop();
        ui->statusBar->showMessage("Connection status: Disconnected (state="+QString::number(state)+")");
        return;
    }
}
*/

//this opens a wave and display it's content
void MainWindow::openWave(void)
{
    //FIXME: this always tells me there is nothing in there, also when there is...
    //ensure there was waves in the list
    //(if theres no waves in the list this would otherwise crash )
    /*
    if (ui->listView->model()->children().count() < 1)
    {
        //FIXME: use a QMessageBox instead
        QErrorMessage *error = new QErrorMessage(this);
        error->showMessage("No waves in the list!");
        return;
    }
    */

    //recover the wavelet id
    QByteArray rootWaveletId = ui->listView->model()->data(ui->listView->currentIndex(), Qt::DisplayRole).toByteArray();

    //instruct the controller to open the wavelet, we'll be notified when we get the actual data back from the server
    m_acm->openWavelet( rootWaveletId );

    //temp, opens gui page, sets wave name at top
    //currentWaveID = ui->listView->model()->data( ui->listView->currentIndex(), PyGoWaveList::WaveIdRole ).toByteArray();
    //QString waveName = ui->listView->model()->data( ui->listView->currentIndex()).toString();
    ui->stackedWidget->setCurrentIndex(2);
    lastOpenedPanel=2;
    //set application state
    currentstate = MainWindow::ViewingBlips;
    //ui->SelectedWave->setTitle(" "+waveName+" ");
    ui->SelectedWave->setTitle(" "+rootWaveletId+" ");
    //clear the blip store;
    arblips.clear();

    //clear existing list
    arblipDisplay->getListWidget()->clear();

    // Retrieve the blips from the blipstore and add them to the list;
    QList<ARBlip> orderedCopy = arblips.getBlipsWithin(currentPosition,100);

    QList<ARBlip>::const_iterator arblip_iterator;
    for (arblip_iterator =  orderedCopy.constBegin(); arblip_iterator !=  orderedCopy.constEnd(); ++arblip_iterator)
    {
        //create arblip list item from blip;
        ARBlipListItem* newblip = new ARBlipListItem(*arblip_iterator, currentPosition);
        //add it to list;
        arblipDisplay->getListWidget()->addItem(newblip);
    }
}


//display the blip text into the appropriate text box
void MainWindow::displayBlipText(QListWidgetItem* blipitem)
{
    ARBlipListItem* selectedblip = dynamic_cast< ARBlipListItem * >( blipitem );
    ui->blipBox->setText(selectedblip->getBlipsDataAsText());
}


//sets the users current location
void MainWindow::setClientLocation(){

    //get name from menu item clicked
    QAction *MenuItem = qobject_cast<QAction *>(sender());
    QString locationName = MenuItem->text();

    //Locations are easy to add
    if (locationName=="0/0/0"){
        currentPosition.Xpos=0;
        currentPosition.Ypos=0;
        currentPosition.Zpos=0;

    }
    if (locationName=="Tilburg"){
        currentPosition.Xpos=5.07766;
        currentPosition.Ypos=51.5585;
        currentPosition.Zpos=0;

    }
    if (locationName=="New York"){
        currentPosition.Xpos=-73.9684;
        currentPosition.Ypos=40.7779;
        currentPosition.Zpos=0;

    }
    if (locationName=="London"){
        currentPosition.Xpos=-0.128167;
        currentPosition.Ypos=51.5083;
        currentPosition.Zpos=0;

    }
    //update status bar
  ui->statusBar->showMessage("Client location set to "+locationName);

    //update the list
     updateARBlipList();


}

//react to range changes by the user
void MainWindow::changeRangeLimit()
{

    //FIXME: Rather messy
    //get new limit
    //get name from menu item clicked
    QAction *MenuItem = qobject_cast<QAction *>(sender());
    QString rangeName = MenuItem->text();
     bool ok;
     int range=0;
    if (rangeName=="infinite")
    {
    range = 40000000;
    } else {

    //if it was specified ink
    if (rangeName.right(2)=="km"){
        QString rangeS = rangeName.mid(0,rangeName.length()-2);
        range = rangeS.toInt(&ok);
        range = range * 1000;
    } else if (rangeName.right(1)=="m") {
        QString rangeS = rangeName.mid(0,rangeName.length()-1);
        range = rangeS.toInt(&ok);
    }


    };
    if (!ok){
        range = 40000000;
    }
    //default to infinite (effectively the size of the earth in meters!)


    //Store range in variable
    rangeLimit = range;

    //update the actual list using the current range
    updateARBlipList();
}

//updates the visible list of blips
void MainWindow::updateARBlipList()
{
    //get a subset of blips in range from the current blip store
    QList<ARBlip> blipSubset = arblips.getBlipsWithin(currentPosition,rangeLimit);

    //clear existing list
    arblipDisplay->getListWidget()->clear();

    //fill the table with them
    QList<ARBlip>::const_iterator arblip_iterator;
    for (arblip_iterator =  blipSubset.constBegin(); arblip_iterator !=  blipSubset.constEnd(); ++arblip_iterator)
    {
        //create arblip list item from blip;
        ARBlipListItem* newblip = new ARBlipListItem(*arblip_iterator,currentPosition);
        //add it to list;
        arblipDisplay->getListWidget()->addItem(newblip);
    }
}

//show the map centered at the current selected blip;
//if no blip is selected, an error is prompted to the user
void MainWindow::goToMap()
{
    //FIXME: this is ugly as hell, where is the nice error window in qt?
    //check if an item is actually selected
    if( arblipDisplay->getListWidget()->currentItem() == NULL )
    {
        //FIXME: use a QMessageBox instead
        QMessageBox *error = new QMessageBox(this);
        error->setText("No ARBlip selected, please select one first");
        error->show();
        return;
    }

    //get currently selected blip
    ARBlipListItem* selectedblip = dynamic_cast< ARBlipListItem * >( arblipDisplay->getListWidget()->currentItem() );

    //set it as the blip currently being edited
    currentlyEditing = selectedblip->getARBlip();

    //TODO:
    //we will probably need co-ordinate conversion here, seeing as the arblip co-ordinates can be done in
    //a few ways, and the map can also potentialy be using a few different types!

    double blipx = selectedblip->getARBlip().getX();
    double blipy = selectedblip->getARBlip().getY();
    mapControl->setView(QPointF(blipx,blipy));
    mapControl->setZoom(7);

    //clear first
    ARLayer->clearGeometries();

    //add the dots on the map
    drawARDots();

    ui->stackedWidget->setCurrentIndex(3);
    lastOpenedPanel=3;
}

void MainWindow::drawARDots(void)
{

    //clear existing dors
    arDots.clear();

    //draw all the points in the map, using the range
    QList<ARBlip> blipSubset = arblips.getBlipsWithin(currentPosition,rangeLimit);

    for(int i = 0; i < blipSubset.size(); i++)
    {
        ARBlip arblip = blipSubset.at(i);
        //create a dot on the map
        //Point *p = new Point( arblip.getLoc().Xpos, arblip.getLoc().Ypos, new QPixmap( QString("point.xpm") ), arblip.getDataAsString() );
        ImagePoint *p = new ImagePoint( arblip.getLoc().Xpos, arblip.getLoc().Ypos, QCoreApplication::applicationDirPath()+"/point.xpm", arblip.getRefID() );
        arDots.append(p);
        //add it to current layer
        ARLayer->addGeometry( p );


    }
}

//update a single ar dot
void MainWindow::updateARDot(ARBlip blip)
{
    //search for correct dot
    for (int i=0;i<arDots.length(); i++){

        if (arDots.at(i)->name()==blip.getRefID()){
            //set the point to match the blips log and lat
            arDots.at(i)->setCoordinate(QPointF(blip.getX(),blip.getY()));
            qDebug()<<"co-ordinates updated to "<<blip.getX()<<" - "<<blip.getY();

            //should only be one dot per arblip so return
            return;

        }


    }
    qDebug()<<"No ARBlip dot found";

    return;
}

//zooms in and out the map view
void MainWindow::zoomMap(int zoomto)
{
    mapControl->setZoom(zoomto);
}

/*
//this method is good for both inserted and deleted text
void MainWindow::updateARBlip( const PyGoWave::Blip *blip )
{
    //a new arblip
    ARBlip *newARBlip = new ARBlip();
    //fill it with current stuffs
    newARBlip->loadFromString(blip->content());
    newARBlip->setReferanceID( blip->id() );

    //add the blip to the list
    arblips.addBlip( *newARBlip );
    //show the changed blips
    updateARBlipList();

    //update specific rather then redraw the lot
    updateARDot(*newARBlip);

    //clear the dots
    //ARLayer->clearGeometries();

    //draw dots on the map    
    //drawARDots();

}
*/

void MainWindow::acm_arblipsUpdated()
{
    qDebug("Arblip list is being updated elsewere...");
    updateARBlipList();
}


//assign the current position on the map to the current selected arblip
void MainWindow::setARBlipLocation()
{
    qDebug()<<"setting location";


    //get position
    double x = mapControl->currentCoordinate().x();
    double y = mapControl->currentCoordinate().y();

     qDebug()<<"getting selected blip";

    //get currently selected blip
 //  ARBlipListItem* selectedblip = dynamic_cast< ARBlipListItem * >( arblipDisplay->getListWidget()->currentItem() );
   // ARBlip ARblipToUpdate = selectedblip->getARBlip();

     //current blip being edited is now stored in "currentlyEditing"
    ARBlip ARblipToUpdate = currentlyEditing;
     ARblipToUpdate.setX(x);
    ARblipToUpdate.setY(y);

      qDebug()<<"updateing blips location";

    //update its location;
    //arblips.addBlip(ARblipToUpdate);
    //(adding a blip updates it if it already exists)

    //delete the dots from the map
    //ARLayer->clearGeometries();

    //update specific rather then redraw the lot
    qDebug()<<"updateing dots map location ("<<ARblipToUpdate.getRefID();
    //updateARDot(ARblipToUpdate);

    //mapControl->updateRequestNew();

    //update the changes also on the server
    m_acm->updateARBlip(ARblipToUpdate.getRefID(), ARblipToUpdate.storeToString());

    //Fix Me?: This might be a bit ugly, I store the row, update the list, and then set the selection back to the row again
    // This works, as long as its a blip being changed, but if one is deleted in the meantime this will mess up :-/
    // Purhapes the "get currently selected blip"  should be stored from the moment the user goes to edit a blip? (ie, from before the map appears?)
    //get current selected row
   // int row = arblipDisplay->getListWidget()->currentRow();

    //update the list too;
    //updateARBlipList();

    //reselect the current selection
   // arblipDisplay->getListWidget()->setCurrentRow(row);

    //turn page to list (disabled to make it easier to check its working)
  // ui->stackedWidget->setCurrentIndex(2);
  //  lastOpenedPanel=2;
  //  currentstate = MainWindow::ViewingBlips;
}


//called when the map is moved?
void MainWindow::mapViewChanged(QPointF newloc, int newzoom)
{
    //which is log which is lat?
    QString xs = "";
    xs.setNum(newloc.x());
    QString ys = "";
    ys.setNum(newloc.y());

    QString labtext = "location:  x(lon)="+xs+"  y(lat)="+ys;

    ui->statusBar->showMessage(labtext);
}

//menu for map types
void MainWindow::createMapMenus()
{
        mapMenu = menuBar()->addMenu("&Map Provider");
        mapMenu->addAction(osmAction);
        mapMenu->addAction(yahooActionMap);
        mapMenu->addAction(yahooActionSatellite);

        //FIXME: we either need to fix this or to completely remove the google map from code
        //Currently not working, so disabled
        //Think its a problem with the API (so not our problem)
        // mapMenu->addAction(googleActionMap);

        mapMenu->addSeparator();
}

//called when another map provider is selected, updates the map displayed accordingly
void MainWindow::mapProviderSelected(QAction* action)
{
    //this part is common
    int zoom = mapAdapter->adaptedZoom();
    mapControl->setZoom(0);

    //variable part
    if (action == osmAction)
    {
        mapAdapter = new OSMMapAdapter();
    }
    else if (action == yahooActionMap)
    {
        mapAdapter = new YahooMapAdapter();
    }
    else if (action == yahooActionSatellite)
    {
        QPointF a = mapControl->currentCoordinate();
        mapAdapter = new YahooMapAdapter("us.maps3.yimg.com", "/aerial.maps.yimg.com/png?v=1.7&t=a&s=256&x=%2&y=%3&z=%1");
     }
    else if (action == googleActionMap)
    {
        mapAdapter = new GoogleMapAdapter();
     }

    //this part is also common
    layer->setMapAdapter(mapAdapter);
    //ARLayer->setMapAdapter(mapAdapter);
    mapControl->updateRequestNew();
    mapControl->setZoom(zoom);
}


//show the arblip creation form
void MainWindow::on_postNewBlip_clicked()
{
    ui->stackedWidget->setCurrentIndex(4);
    //set application state
    currentstate = MainWindow::AddingBlip;
}

void MainWindow::editSelectedBlip_clicked()
{
    ui->stackedWidget->setCurrentIndex(4);
    //set application state
    currentstate = MainWindow::EditingBlip;
}

void MainWindow::deleteSelectedBlip_clicked()
{
    //get currently seleted (maybe this should be done as its own method, seeing as its used at least twice with near identical code)
    if( arblipDisplay->getListWidget()->currentItem() == NULL )
    {
        QMessageBox *error = new QMessageBox(this);
        error->setText("No ARBlip selected, please select one first");
        error->show();
        return;
    }

    //get currently selected blip
    ARBlipListItem* selectedblip = dynamic_cast< ARBlipListItem * >( arblipDisplay->getListWidget()->currentItem() );

    //confirmation
    QMessageBox msgBox;
     msgBox.setText("Are you sure you wish to delete this arblip?");
     msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
     msgBox.setDefaultButton(QMessageBox::Cancel);
     int ret = msgBox.exec();

     switch (ret) {
       case QMessageBox::Cancel:
            qDebug()<<"canceled delete blip";
           break;
       case QMessageBox::Ok:
           // delete the blip
           qDebug()<<"delete blip "<<selectedblip->getARBlip().getRefID();

           m_acm->deleteARBlip( selectedblip->getARBlip().getRefID() );
           break;
       default:
           // should never be reached
           break;
     }


}

//create a new arblip with the data obtained from the form and notify the server
void MainWindow::on_submitNewBlip_clicked()
{

    //This should deal with both submiting a new blip, and changing an existing one?
    //We can use the currentstate to determain which should be done.

    //ARBlip

    //FIXME: shouldnt the username and and ID be set correctly? yes, we should... added to the todo list =)
    ARBlip newARBlip("ID", "Mr. Peep",
                       ui->xPosEdit->text().toDouble(), ui->yPosEdit->text().toDouble(), ui->zPosEdit->text().toDouble(),
                       ui->rollEdit->text().toInt(), ui->pitchEdit->text().toInt(), ui->yawEdit->text().toInt(),
                       QString(ui->arblipDataEdit->text()),
                       QDateTime::currentDateTime() );

    //create a new blip with the given body
    m_acm->addARBlip(newARBlip.storeToString());

    //turn page to list
    ui->stackedWidget->setCurrentIndex(2);
    lastOpenedPanel=2;
    currentstate = MainWindow::ViewingBlips;
}

void MainWindow::addNewBlipFromMap()
{
    QPointF currentlocation = mapControl->currentCoordinate();
    QString xs = "";
    xs.setNum(currentlocation.x());
    QString ys = "";
    ys.setNum(currentlocation.y());

    qDebug()<<"adding new blip at"<<xs<<","<<ys;
    //set interface to correct page
    ui->stackedWidget->setCurrentIndex(4);
    // (so it knows if its adding or editing a blip)
    currentstate = MainWindow::AddingBlip;

    //auto-fill location
    ui->xPosEdit->setText(xs);
    ui->yPosEdit->setText(ys);
    ui->zPosEdit->setText("0");
    ui->yawEdit->setText("0");
    ui->pitchEdit->setText("0");
    ui->rollEdit->setText("0");

    //set the cursor to the text box, so they can type their content.
    ui->arblipDataEdit->setFocus();

}

void MainWindow::cancelSubmit(){

    qDebug()<<"canceling  "<<lastOpenedPanel;
    //return to the last page opened
    ui->stackedWidget->setCurrentIndex(lastOpenedPanel);

}


void MainWindow::inviteUserToWave()
{
    QString newuser = ui->inviteNewUser->text();
    qDebug()<<"inviting new user to wave:"<<newuser;
    //TODO: WAVELET_ADD_PARTICIPANT?
    //qDebug<<this->wavelet->allParticipants().at(0);
    if ( !m_acm->addParticipant( newuser ) )
    {
            QMessageBox::warning(this, tr("Cannot add participant"), tr("This participant is already on the wave!"));
    }
    ui->inviteNewUser->clear();
}


void MainWindow::gotolocation()
{
    QString url = ui->enterLocations->currentText();
    double lo= 0;
    double la=0;
    int zoom = 0;
    //check if its a googlemap

    if (url.startsWith("http://maps.google")){
         qDebug()<<"google map url entered";

         //extract the log/lat from it

         //note, a max(x,y) function would be helpfull here but dont know how to do that in qt
         int start1 = (url.indexOf("&ll=")+4);
         int start2 = (url.indexOf("?ll=")+4);
         int start = (start1>start2)?start1:start2;


          int end = url.indexOf("&",start)-1;

          QString loglat = url.mid(start,end-(start));
          QString log  = loglat.split(",").at(0);
          QString lat  = loglat.split(",").at(1);
          qDebug()<<loglat<<" log="<<log<<" lat="<<lat;
           lo = log.toDouble();
           la = lat.toDouble();

           //get zoom
           QString zooms =  url.mid(url.indexOf("z=")+2,url.length());
           zoom = zooms.toInt();
           qDebug()<<" zoom="<<zoom;
           mapControl->setZoom(zoom);

    }

    //http://maps.yahoo.com/#mvt=m&lat=52.376934&lon=4.897049&zoom=11
    if (url.startsWith("http://maps.yahoo"))
    {
        qDebug()<<"yahoo map url entered";
        //extract the log/lat from it
         int start = url.indexOf("lat=")+4;
         int end = url.indexOf("&z",start)-1;

         QString loglat = url.mid(start,end-(start));
         QString log  = loglat.split("&lon=").at(0);
         QString lat  = loglat.split("&lon=").at(1);
         qDebug()<<loglat<<" log="<<log<<" lat="<<lat;
          lo = log.toDouble();
          la = lat.toDouble();

    }
//http://www.openstreetmap.org/?lat=0&lon=0&zoom=8&layers=B000FTF
    if (url.startsWith("http://www.openstreetmap"))
    {
        qDebug()<<"open street map url entered";
        //extract the log/lat from it
         int start = url.indexOf("lat=")+4;
         int end = url.indexOf("&z",start);

         QString loglat = url.mid(start,end-(start));
         QString log  = loglat.split("&lon=").at(0);
         QString lat  = loglat.split("&lon=").at(1);
         qDebug()<<loglat<<" log="<<log<<" lat="<<lat;
          lo = log.toDouble();
          la = lat.toDouble();

    }
    //location
    mapControl->moveTo(QPointF(la,lo));



   // mapControl->updateRequest( mapControl->visibleRegion().boundingRect());  //not sure about this, sometimes it came out white, I think this ensures it redraws.


}

void MainWindow::addWave(QString waveID, QDateTime lastChange, QString title)
{
    WaveModel wm(waveID, lastChange, title);
}
